package com.kim.authorization.server.config;

import com.kim.authorization.server.config.jwt.CustomTokenEnhancer;
import com.kim.authorization.server.config.jwt.CustomerAccessTokenConverter;
import com.kim.authorization.server.config.util.JwtSecretProperties;
import com.kim.oauth.common.token.CustomRedisTokenStore;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

import javax.sql.DataSource;
import java.security.KeyPair;

/**
 * TokenStore配置类
 */
@Slf4j
@Configuration
public class TokenStoreConfig {

    /**
     * redis
     */
    private final RedisTemplate<String, Object> redisTemplate;

    /**
     * 数据源
     */
    private final DataSource dataSource;

    public TokenStoreConfig(DataSource dataSource,
                            @Autowired(required = false)
                                    RedisTemplate<String, Object> redisTemplate) {
        this.dataSource = dataSource;
        this.redisTemplate = redisTemplate;
    }

    /**
     * token存储
     *
     * @return org.springframework.security.oauth2.provider.token.store.JdbcTokenStore
     */
    @Bean
    @Deprecated
    @ConditionalOnProperty(prefix = "surge.oauth2.token-store", name = "type", havingValue = "jdbc")
    public JdbcTokenStore jdbcTokenStore() {
        log.info("使用  --->  jdbcTokenStore 存储token");
        return new JdbcTokenStore(dataSource);
    }

    /**
     * 使用redis方式存储token
     * <p>
     * 还是官方实现的更好用,刷新token后原token不可用，自己实现的这个地方尚未实现
     * 但是自己实现的customRedisTokenStore 可以自定义token存储内容
     * </p>
     */
    @Bean
    @ConditionalOnProperty(prefix = "surge.oauth2.token-store", name = "type", havingValue = "redis", matchIfMissing = true)
    public RedisTokenStore redisTokenStore() {
        log.info("使用  --->  RedisTokenStore 存储token");
        return new RedisTokenStore(redisTemplate.getConnectionFactory());
    }

    /**
     * 使用redis方式存储token
     *
     * @return org.surge.oauth2common.token.CustomRedisTokenStore
     */
    @Bean
    @ConditionalOnProperty(prefix = "surge.oauth2.token-store", name = "type", havingValue = "redis-custom")
    public CustomRedisTokenStore customRedisTokenStore() {
        log.info("使用  --->  CustomRedisTokenStore 存储token");
        CustomRedisTokenStore customRedisTokenStore = new CustomRedisTokenStore();
        customRedisTokenStore.setRedisTemplate(redisTemplate);
        return customRedisTokenStore;
    }

    /**
     * JwtTokenStore配置类
     */
    @Configuration
    @ConditionalOnProperty(prefix = "surge.oauth2.token-store", name = "type", havingValue = "jwt")
    @EnableConfigurationProperties(JwtSecretProperties.class)
    public static class JwtTokenConfig {

        /**
         * jks证书配置
         */
        private final JwtSecretProperties jwtSecretProperties;

        public JwtTokenConfig(JwtSecretProperties jwtSecretProperties) {
            this.jwtSecretProperties = jwtSecretProperties;
        }

        /**
         * 配置TokenStore
         */
        @Bean
        public JwtTokenStore tokenStore() {
            log.info("使用  --->  JwtTokenStore 存储token");
            return new JwtTokenStore(accessTokenConverter());
        }

        /**
         * 配置jwt转换器
         */
        @Bean
        public JwtAccessTokenConverter accessTokenConverter() {
            log.info("Create --->  JwtAccessTokenConverter ");
            JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
            KeyPair keyPair = new KeyStoreKeyFactory(
                    new ClassPathResource(jwtSecretProperties.getPath()),
                    jwtSecretProperties.getPwd().toCharArray())
                    .getKeyPair(jwtSecretProperties.getAlias());
            converter.setKeyPair(keyPair);
            // 替换默认的token生成方式
            converter.setAccessTokenConverter(new CustomerAccessTokenConverter());
            return converter;
        }


        /**
         * 自定义token增强器
         */
        @Bean
        public TokenEnhancer customTokenEnhancer() {
            log.info("Create --->  customTokenEnhancer ");
            return new CustomTokenEnhancer();
        }
    }
}
